VoiceCard β Multilingual Voice Introduction Generator
VoiceCard β Multilingual Voice Introduction Generator
You give it an API key + config. It gives you a ready component.
What It Actually Is
A CLI tool + generator that takes:
- Your TTS provider API key (ElevenLabs, OpenAI, etc.)
- A single
voice.config.tsfile - Your intro text per language (or just one language + auto-translate)
And outputs:
- A self-contained React component (
VoiceCard.tsx) β paste into any project - A self-contained Svelte component (
VoiceCard.svelte) β paste into any project - Pre-generated audio files (fetched from the API and saved locally)
- Zero runtime API calls β audio is baked in at generation time
The visitor's browser never touches your API key. Never calls any external API. Just plays a local audio file.
The Mental Model
You run: npx voicecard generate
It does:
1. Reads voice.config.ts
2. Calls your TTS API with each language's text
3. Downloads + saves audio files to /public/voicecard/
4. Writes VoiceCard.tsx (React) β ready to paste
5. Writes VoiceCard.svelte β ready to paste
You get: <VoiceCard /> β drop it anywhere, works offline
No runtime server. No proxy. No API key exposure. Just static files + a component.
Usage: End-to-End in 4 Steps
Step 1 β Install
npm install -g voicecard
# or use without installing:
npx voicecard
Step 2 β Create your config
voice.config.ts in your project root:
import { defineConfig } from 'voicecard';
export default defineConfig({
// --- Who you are ---
owner: {
name: 'Enes YeΕil',
photo: '/images/enes.jpg', // optional, shown in card UI
},
// --- Your TTS provider ---
provider: {
name: 'elevenlabs',
apiKey: process.env.ELEVENLABS_API_KEY, // from .env β never committed
voiceId: 'your-cloned-voice-id', // your voice clone ID
},
// --- Your intro text ---
// Option A: Write each language manually
languages: {
en: {
text: `Hi, I'm Enes. I build tools at the intersection of design and engineering.
I care about making complex things feel simple.`,
label: 'English',
flag: 'π¬π§',
},
tr: {
text: `Merhaba, ben Enes. TasarΔ±m ve mΓΌhendisliΔin kesiΕiminde araΓ§lar ΓΌretiyorum.
KarmaΕΔ±k Εeyleri sade hissettirmek benim iΓ§in ΓΆnemli.`,
label: 'TΓΌrkΓ§e',
flag: 'πΉπ·',
},
de: {
text: `Hallo, ich bin Enes. Ich entwickle Tools an der Schnittstelle von Design und Engineering.`,
label: 'Deutsch',
flag: 'π©πͺ',
},
},
// --- Option B: Write one language, auto-translate the rest ---
// autoTranslate: {
// source: 'en',
// targets: ['tr', 'de', 'fr', 'ja', 'zh', 'ar', 'es', 'pt'],
// provider: 'deepl', // or 'openai', 'google'
// apiKey: process.env.DEEPL_API_KEY,
// },
// --- Output ---
output: {
audioDir: 'public/voicecard', // where audio files are saved
componentDir: 'src/components', // where the component is written
frameworks: ['react', 'svelte'], // which components to generate
},
// --- UI ---
ui: {
theme: 'card', // 'minimal' | 'card' | 'floating'
trigger: 'button', // 'button' | 'auto'
defaultLanguage: 'en',
showTranscript: true,
showLanguageSwitcher: true,
},
});
Step 3 β Generate
npx voicecard generate
Output in terminal:
β Fetching audio: en β public/voicecard/intro-en.mp3 (28KB)
β Fetching audio: tr β public/voicecard/intro-tr.mp3 (24KB)
β Fetching audio: de β public/voicecard/intro-de.mp3 (31KB)
β Writing component: β src/components/VoiceCard.tsx
β Writing component: β src/components/VoiceCard.svelte
Done. Drop <VoiceCard /> into your page.
Step 4 β Drop it in
React (Next.js, Vite, Remix, etc.):
import VoiceCard from '@/components/VoiceCard';
export default function Hero() {
return (
<main>
<VoiceCard />
<h1>Enes YeΕil</h1>
</main>
);
}
Svelte (SvelteKit, etc.):
<script>
import VoiceCard from '$lib/components/VoiceCard.svelte';
</script>
<VoiceCard />
<h1>Enes YeΕil</h1>
That's it. No config props to pass. Everything is baked into the generated component.
What the Generated Component Contains
The generated file is fully self-contained and readable. No magic. No opaque blob.
// VoiceCard.tsx β generated by voicecard on 2026-03-09
// DO NOT EDIT β re-run `npx voicecard generate` to regenerate
const VOICECARD_CONFIG = {
owner: { name: 'Enes YeΕil', photo: '/images/enes.jpg' },
defaultLanguage: 'en',
languages: {
en: { label: 'English', flag: 'π¬π§', audio: '/voicecard/intro-en.mp3',
transcript: 'Hi, I\'m Enes. I build tools...' },
tr: { label: 'TΓΌrkΓ§e', flag: 'πΉπ·', audio: '/voicecard/intro-tr.mp3',
transcript: 'Merhaba, ben Enes...' },
de: { label: 'Deutsch', flag: 'π©πͺ', audio: '/voicecard/intro-de.mp3',
transcript: 'Hallo, ich bin Enes...' },
},
ui: { theme: 'card', trigger: 'button', showTranscript: true }
};
// ... ~150 lines of clean React component code ...
export default function VoiceCard() { ... }
It's a normal component you can read, fork, and modify. The generator just saves you from writing it.
CLI Commands
# Generate components + audio from config
npx voicecard generate
# Only re-fetch audio (config didn't change, just refreshing voice)
npx voicecard audio
# Only regenerate components (audio already exists, UI tweak)
npx voicecard component
# Preview what would be generated without writing files
npx voicecard generate --dry-run
# Validate your config before running
npx voicecard validate
# List all available TTS providers
npx voicecard providers
# Check which languages support your chosen provider's voice clone
npx voicecard languages --provider elevenlabs
# Interactive setup wizard (for first-time users)
npx voicecard init
Supported TTS Providers
All providers are plug-and-play via the provider.name config key.
| Provider | Voice Cloning | Languages | Notes |
|---|---|---|---|
elevenlabs |
Yes | 32 | Best quality for cloned voice |
openai |
No (preset voices) | 57 | Fast, cheap, great quality |
deepgram |
Yes | 36 | Good alternative to ElevenLabs |
azure |
Yes (Custom Neural) | 140+ | Most language coverage |
google |
Yes (Custom Voice) | 220+ | Max coverage, complex setup |
browser |
No | varies | Zero cost, no API key needed |
You only ever set one provider. The CLI calls that provider's API during generation. At runtime, the visitor's browser just plays MP3 files.
Auto-Translate Feature
If you don't speak 10 languages but want 10 language versions, the autoTranslate block handles it:
autoTranslate: {
source: 'en', // your master language
targets: ['tr', 'de', 'fr', 'ja', 'zh', 'ar', 'es', 'pt', 'hi', 'ko'],
provider: 'deepl', // translation API
apiKey: process.env.DEEPL_API_KEY,
reviewDir: 'voicecard/translations', // saves translated text for your review
}
What happens:
- Translates your English text to all target languages
- Saves translation files to
reviewDirβ you review them before generating audio - Once you approve (or edit), run
npx voicecard generateto produce audio
The review step is intentional. Auto-translated text for your personal intro can be awkward. You want to catch that before it's spoken in your voice.
Project Structure After Generation
your-project/
βββ voice.config.ts β you write this
βββ .env β ELEVENLABS_API_KEY=... (gitignored)
β
βββ public/
β βββ voicecard/
β βββ intro-en.mp3 β generated audio files
β βββ intro-tr.mp3
β βββ intro-de.mp3
β
βββ voicecard/
β βββ translations/ β auto-translated text (for review)
β βββ de.txt
β βββ fr.txt
β
βββ src/components/
βββ VoiceCard.tsx β generated React component
βββ VoiceCard.svelte β generated Svelte component
Generated Component: UI Themes
All three themes are included in the generated file. You switch via ui.theme in config then regenerate β or just change the theme prop at runtime if you want to toggle it dynamically.
minimal
[ βΆ Hear my intro ] π¬π§ πΉπ· π©πͺ
Play button + language flags. Fits inline anywhere.
card
βββββββββββββββββββββββββββββββ
β [photo] Enes YeΕil β
β βΆ Hear my intro β
β ββββββββββββ β β waveform progress bar
β π¬π§ English πΉπ· TΓΌrkΓ§e π©πͺ β
β βΌ Read transcript β
βββββββββββββββββββββββββββββββ
Bio card widget. Good as a hero section element.
floating
βββββββββββββ
β π Listen β β bottom-right corner, always visible
βββββββββββββ
Non-intrusive. Expands on click to show full card.
Security Model
This is the right way to think about it:
Generation time (YOUR machine):
voice.config.ts + API key β CLI β API call β MP3 files saved locally
Runtime (visitor's browser):
HTML page loads β component plays /public/voicecard/intro-en.mp3
β zero API calls, zero key exposure, zero external dependencies
Your API key is only used at generation time, on your machine. It's in .env, gitignored. The output files (MP3s + component) contain no keys.
This also means the component works offline, behind a firewall, or anywhere β because it's just audio files.
Regeneration Strategy
Audio files are expensive to regenerate (API calls cost money + time). The CLI is smart about this:
npx voicecard generate
# Only fetches audio for languages where text changed since last run
# Compares hash of text content against a lockfile: voicecard.lock.json
# Skips unchanged languages
# Always regenerates components (cheap β local operation)
voicecard.lock.json β tracks what was generated:
{
"generated": "2026-03-09T14:22:00Z",
"provider": "elevenlabs",
"voiceId": "abc123",
"hashes": {
"en": "sha256:a1b2c3...",
"tr": "sha256:d4e5f6...",
"de": "sha256:g7h8i9..."
}
}
Commit voicecard.lock.json and the MP3 files to git. Don't commit voice.config.ts's API key (use env vars).
Accessibility
Hard requirements, not optional:
- Transcript always available as accessible text (visible or toggle-able)
aria-liveregion announces playback state to screen readers- Full keyboard control: Space to play/pause, Escape to stop, Tab through languages
- No autoplay β ever. The
trigger: 'auto'config option plays only after a user gesture has occurred on the page - Respects
prefers-reduced-motionβ animations disabled, no pulsing waveform - Color contrast AA minimum on all themes
npx voicecard init β Setup Wizard
For first-time users, the interactive wizard eliminates config guesswork:
$ npx voicecard init
? Which TTS provider do you want to use?
β― ElevenLabs (voice cloning, 32 languages)
OpenAI TTS (no cloning, 57 languages, cheaper)
Browser TTS (free, no API key)
? Paste your ElevenLabs API key: **********************
? Do you have a voice clone, or should we create one?
β― I have a voice clone ID already
Walk me through creating one
? What frameworks do you need?
β― β React
β Svelte
β Vanilla HTML
? Which languages do you want? (space to select)
β― β English
β Turkish
β German
β French
β Japanese
...
? Write your intro in English:
β― [text input]
? Auto-translate to selected languages?
β― Yes β I'll review translations before generating audio
No β I'll write each language myself
β Created voice.config.ts
β Created .env (with your API key)
β Added voicecard/ and .env to .gitignore
Run `npx voicecard generate` when ready.
Roadmap
v1 β Core (what's described above)
- CLI generator
- ElevenLabs + OpenAI providers
- React + Svelte output
- 3 themes
- Auto-translate with review step
v2 β Studio
- Browser-based UI to run the generator without a terminal (
npx voicecard studio) - Drag-and-drop to record your own voice instead of using a TTS API
- Live preview of the component before generating
v3 β Publish
npx voicecard publishβ push audio files to Cloudflare R2 or S3 directly- CDN URLs instead of local
/public/paths - Version management (keep old audio versions when you update your intro)
Created: March 2026 β World of Ideas